/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-10-01     Rei2       the first version
 */

#include <rtthread.h>
#include <rtdevice.h>
#include <stdio.h>
#include "drv_touch.h"
#include "drv_if8080.h"
#include "debug.h"

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>


#define WHITE                            0xFFFF
#define BLACK                            0x0000
#define BLUE                             0x001F
#define BRED                             0xF81F
#define GRED                             0xFFE0
#define GBLUE                            0x07FF
#define RED                              0xF800
#define MAGENTA                          0xF81F
#define GREEN                            0x07E0
#define CYAN                             0x7FFF
#define YELLOW                           0xFFE0
#define BROWN                            0xBC40
#define BRRED                            0xFC07
#define GRAY                             0x8430

#define RESET_PIN   GET_PIN(E,0)

/**
  * @brief  configures the lcd.
  *         this function must be called before any write/read operation
  *         on the lcd.
  * @param  none
  * @retval none
  */
void lcd_init(void)
{
    uint16_t chip_id;

    /* reset pa.01 */
    rt_pin_write(RESET_PIN, RT_FALSE);
    rt_thread_mdelay(100);

    /* set pa.01 */
    rt_pin_write(RESET_PIN, RT_TRUE);
    rt_thread_mdelay(200);

    drv_if8080_write_command(0x01);
    rt_thread_mdelay(120);

    drv_if8080_write_command(0x11);
    rt_thread_mdelay(120);

    /* read id */
    drv_if8080_write_command(0x00);
    rt_thread_mdelay(5);

    drv_if8080_write_command(0xd3);

    chip_id = drv_if8080_read_data();
    chip_id = drv_if8080_read_data();
    chip_id = drv_if8080_read_data();
    chip_id = chip_id << 8;
    chip_id |= drv_if8080_read_data();

    LOG_I("Chip ID %04X", chip_id);

    drv_if8080_write_command(0xF0);
    drv_if8080_write_data(0xC3);

    drv_if8080_write_command(0xF0);
    drv_if8080_write_data(0x96);

    drv_if8080_write_command(0x36);
    drv_if8080_write_data(0x28);

    drv_if8080_write_command(0x3A);
    drv_if8080_write_data(0x05);

    drv_if8080_write_command(0xB4);
    drv_if8080_write_data(0x01);

    drv_if8080_write_command(0xB6);
    drv_if8080_write_data(0x8A);
    drv_if8080_write_data(0x07);
    drv_if8080_write_data(0x3B);

    drv_if8080_write_command(0xB7);
    drv_if8080_write_data(0xC6);

    drv_if8080_write_command(0xB9);
    drv_if8080_write_data(0x02);
    drv_if8080_write_data(0xE0);

    drv_if8080_write_command(0xC0);
    drv_if8080_write_data(0xC0);
    drv_if8080_write_data(0x64);

    drv_if8080_write_command(0xC1);
    drv_if8080_write_data(0x1D);

    drv_if8080_write_command(0xC2);
    drv_if8080_write_data(0xA7);

    drv_if8080_write_command(0xC5);
    drv_if8080_write_data(0x18);

    drv_if8080_write_command(0xE8);
    drv_if8080_write_data(0x40);
    drv_if8080_write_data(0x8A);
    drv_if8080_write_data(0x00);
    drv_if8080_write_data(0x00);
    drv_if8080_write_data(0x29);
    drv_if8080_write_data(0x19);
    drv_if8080_write_data(0xA5);
    drv_if8080_write_data(0x33);

    drv_if8080_write_command(0xE0);
    drv_if8080_write_data(0xF0);
    drv_if8080_write_data(0x0B);
    drv_if8080_write_data(0x12);
    drv_if8080_write_data(0x09);
    drv_if8080_write_data(0x0A);
    drv_if8080_write_data(0x26);
    drv_if8080_write_data(0x39);
    drv_if8080_write_data(0x54);
    drv_if8080_write_data(0x4E);
    drv_if8080_write_data(0x38);
    drv_if8080_write_data(0x13);
    drv_if8080_write_data(0x13);
    drv_if8080_write_data(0x2E);
    drv_if8080_write_data(0x34);

    drv_if8080_write_command(0xE1);
    drv_if8080_write_data(0xF0);
    drv_if8080_write_data(0x10);
    drv_if8080_write_data(0x15);
    drv_if8080_write_data(0x0D);
    drv_if8080_write_data(0x0C);
    drv_if8080_write_data(0x07);
    drv_if8080_write_data(0x38);
    drv_if8080_write_data(0x43);
    drv_if8080_write_data(0x4D);
    drv_if8080_write_data(0x3A);
    drv_if8080_write_data(0x16);
    drv_if8080_write_data(0x15);
    drv_if8080_write_data(0x30);
    drv_if8080_write_data(0x35);

    drv_if8080_write_command(0xF0);
    drv_if8080_write_data(0x3C);

    drv_if8080_write_command(0xF0);
    drv_if8080_write_data(0x69);

    drv_if8080_write_command(0x35);
    drv_if8080_write_data(0x00);

    drv_if8080_write_command(0x29);
    drv_if8080_write_command(0x21);

    drv_if8080_write_command(0x2A);
    drv_if8080_write_data(0x00);
    drv_if8080_write_data(0x31);
    drv_if8080_write_data(0x01);
    drv_if8080_write_data(0x0E);

    drv_if8080_write_command(0x2B);
    drv_if8080_write_data(0x00);
    drv_if8080_write_data(0x00);
    drv_if8080_write_data(0x01);
    drv_if8080_write_data(0xDF);

    drv_if8080_write_command(0x2C);
}


/**
  * @brief  this function is set row&column coordinates for lcd.
  * @param  xstart : row coordinates starting vaule.
  * @param  ystart : column coordinates starting vaule.
  * @param  xend : row coordinates ending vaule.
  * @param  yend : column coordinates ending vaule.
  * @retval none
  */
void lcd_setblock(uint16_t xstart, uint16_t ystart, uint16_t xend, uint16_t yend)
{
  /* set row coordinates */
  drv_if8080_write_command(0x2a);
  drv_if8080_write_data(xstart >> 8);
  drv_if8080_write_data(xstart);
  drv_if8080_write_data(xend >> 8);
  drv_if8080_write_data(xend);

  /* set column coordinates */
  drv_if8080_write_command(0x2b);
  drv_if8080_write_data(ystart >> 8);
  drv_if8080_write_data(ystart);
  drv_if8080_write_data(yend >> 8);
  drv_if8080_write_data(yend);

  /* enable write menory */
  drv_if8080_write_command(0x2c);
}

/**
  * @brief  this function is clear the lcd.
  * @param  data : the data to write.
  * @retval none
  */
void lcd_clear(uint16_t color)
{
  uint32_t i;

  lcd_setblock(0, 0, 479, 319);

  for(i = 0; i <  480 * 320; i++)
  {
      drv_if8080_write_data(color);
  }
}


static int display_init(void)
{
    uint8_t tx_buff[32];
    uint8_t rx_buff[32];
    uint8_t *data = &rx_buff[1];
    struct rt_i2c_bus_device *i2c_bus;
    uint8_t color_index = 0;
    const uint16_t color_list[]= {WHITE, BLACK, BLUE, BRED, GRED, GBLUE, RED, MAGENTA, GREEN, CYAN, YELLOW, BROWN, BRRED, GRAY};

    LOG_I("Hello RT-Thread!");

    DEBUG_PIN_INIT();

    drv_touch_init();
    drv_if8080_init();

    lcd_init();
    lcd_clear(RED);

    i2c_bus = (struct rt_i2c_bus_device *)rt_device_find("hwi2c1");
    if (i2c_bus == NULL)
    {
        return -RT_EIO;
    }

#if SOUND_DEBUF_ENABLE == 1
    rt_audio_debug();
#endif

    tx_buff[0] = 0xD2;
    tx_buff[1] = 0x04;

    drv_touch_write_read(i2c_bus, tx_buff, 2, rx_buff, 4);

    uint16_t chip_id = rx_buff[2] + (rx_buff[3] << 8);
    uint16_t project_id = rx_buff[0] + (rx_buff[1] << 8);
    LOG_I("Chip ID %X, project ID %x", chip_id, project_id);

    tx_buff[0] = 0;
    while(1)
    {
//        drv_touch_write_reg(i2c_bus, ucTemp, 1);
        drv_touch_write_read(i2c_bus, tx_buff, 1, rx_buff, 32);
//        for (uint8_t i=0;i<32;i++)
//        {
//            printf("%02X ", rx_buff[i]);
//        }
//        printf("\r\n");
        uint8_t num_of_touches = data[5] & 0x7F;
        if (num_of_touches != 0) {
            size_t index = 0;
            for (uint8_t i = 0; i != num_of_touches; i++) {
              uint8_t id = data[index] >> 4;
              int16_t x = (data[index + 1] << 4) | ((data[index + 3] >> 4) & 0x0F);
              int16_t y = (data[index + 2] << 4) | (data[index + 3] & 0x0F);
              int16_t z = data[index + 4];

              printf("Read touch %d:%d %d/%d\r\n", id, z, x, y);
              index += 5;
              if (i == 0)
                index += 2;
            }
        }

        lcd_clear(color_list[color_index]);
        color_index = (color_index + 1) % (sizeof(color_list)/sizeof(uint16_t));
        rt_thread_mdelay(200);
    }

    return RT_EOK;
}

//INIT_APP_EXPORT(display_init);
